// 用来实现琐碎代码实现;
//   1.日志宏的实现,
//   2.json序列化和反序列化;
//   3.uuid生成;

#pragma once
#include <stdio.h>
#include <time.h>
#include <jsoncpp/json/json.h>
#include <sstream>
#include <iostream>
#include <memory>
#include <string>
#include <random>
#include <chrono>
#include <sstream>
#include <atomic>
#include <iomanip>

namespace RPC
{
    // #define LOG(msg) printf("%s\n", msg)
    // #define LOG(format, msg) printf(format "\n", msg)
    // #define LOG(format, msg) printf("[%s:%d]" format "\n", __FILE__, __LINE__, msg)
    //  #def ine LOG(format, msg){\
//     time_t t = time(NULL);\
//     struct tm* it = localtime(&t);\
//     char time_tmp[32] = {0};\
//     strftime(time_tmp, 31, "%m-%d %T", it);\
//     printf("[%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, msg);\
// }
    // 不定参数...;##连接字符串;
    //  #def ine LOG(format, ...){\
//     time_t t = time(NULL);\
//     struct tm* it = localtime(&t);\
//     char time_tmp[32] = {0};\
//     strftime(time_tmp, 31, "%m-%d %T", it);\
//     printf("[%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__);\
// }

#define LDBG 0
#define LINF 1
#define LERR 2
#define LDEFAULT LDBG

#define LOG(level, format, ...)                                                                       \
    {                                                                                                 \
        if (level >= LDEFAULT)                                                                        \
        {                                                                                             \
            time_t t = time(NULL);                                                                    \
            struct tm *it = localtime(&t);                                                            \
            char time_tmp[32] = {0};                                                                  \
            strftime(time_tmp, 31, "%m-%d %T", it);                                                   \
            fprintf(stdout, "[%s][%s:%d] " format "\n", time_tmp, __FILE__, __LINE__, ##__VA_ARGS__); \
        }                                                                                             \
    }

#define DLOG(format, ...) LOG(LDBG, format, ##__VA_ARGS__)
#define ILOG(format, ...) LOG(LINF, format, ##__VA_ARGS__)
#define ELOG(format, ...) LOG(LERR, format, ##__VA_ARGS__)

    class JSON
    {
    public:
        static bool serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;

            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(val, &ss);
            if (ret != 0)
            {
                ELOG("json serialize failed");
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool unserialize(const std::string& body, Json::Value &val)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            std::string errs;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (ret == false)
            {
                ELOG("json unserialize failed : %s", errs.c_str());
                return false;
            }
            return true;
        }
    };

    class UUID
    {
    public:
        std::string uuid()
        {
            std::stringstream ss;
            // 1. 构造随机数对象;
            std::random_device rd;
            // 2. 随机数种子进行构造伪随机数对象;
            std::mt19937_64 generator(rd());

            // 限定范围;
            std::uniform_int_distribution<int> distribution(0, 255);

            for (int i = 0; i < 8; i++)
            {
                if (i == 4 || i == 6)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << distribution(generator);
            }

            static std::atomic<size_t> seq(1);
            size_t cur = seq.fetch_add(1);
            for (int i = 7; i >= 0; i--)
            {
                if (i == 5)
                    ss << "-";
                ss << std::setw(2) << std::setfill('0') << std::hex << ((cur >> i * 8) & 0xFF);
            }
            return ss.str();
        }
    };
}


